* @param IDatabase $db1
* @param IDatabase ...
* @return array Map of values:
- * - lag: highest lag of any of the DBs
+ * - lag: highest lag of any of the DBs or false on error (e.g. replication stopped)
* - since: oldest UNIX timestamp of any of the DB lag estimates
* - pending: whether any of the DBs have uncommitted changes
* @since 1.27
foreach ( func_get_args() as $db ) {
/** @var IDatabase $db */
$status = $db->getSessionLagStatus();
- $res['lag'] = max( $res['lag'], $status['lag'] );
+ if ( $status['lag'] === false ) {
+ $res['lag'] = false;
+ } elseif ( $res['lag'] !== false ) {
+ $res['lag'] = max( $res['lag'], $status['lag'] );
+ }
$res['since'] = min( $res['since'], $status['since'] );
$res['pending'] = $res['pending'] ?: $db->writesPending();
}
$wrapExtra = array(); // additional wrapped value fields
// Check if there's a risk of writing stale data after the purge tombstone expired
- if ( ( $lag + $age ) > self::MAX_READ_LAG ) {
+ if ( $lag === false || ( $lag + $age ) > self::MAX_READ_LAG ) {
// Case A: read lag with "lockTSE"; save but record value as stale
if ( $lockTSE >= 0 ) {
$ttl = max( 1, (int)$lockTSE ); // set() expects seconds
return true; // no-op the write for being unsafe
// Case C: high replication lag; lower TTL instead of ignoring all set()s
- } elseif ( $lag > self::MAX_READ_LAG ) {
+ } elseif ( $lag === false || $lag > self::MAX_READ_LAG ) {
$ttl = $ttl ? min( $ttl, self::TTL_LAGGED ) : self::TTL_LAGGED;
$this->logger->warning( "Lowered set() TTL for $key due to replication lag." );
// Case D: medium length request with medium replication lag; ignore this set()